/*
 Copyright 2013--Present JMM_PROGNAME
 
 This file is distributed under the terms of the JMM_PROGNAME License.
 
 You should have received a copy of the JMM_PROGNAME License.
 If not, see <JMM_PROGNAME WEBSITE>.
*/
// CREATED    : 8/22/2015
// LAST UPDATE: 9/30/2015

#include "statsxx/machine_learning/restricted_Boltzmann_machine/RBM.hpp"

// STL
#include <cmath> // std::sqrt()

// jScience
#include "jScience/linalg/Matrix.hpp" // Matrix<>
#include "jScience/linalg/Vector.hpp" // Vector<>
#include "jrandnum.hpp"               // rand_num_uniform_Mersenne_twister()


inline restricted_Boltzmann_machine::RBM::RBM(
                                              const int nv,
                                              const int nh
                                              )
{
    this->nvis = nv;
    this->nhid = nh;
    
    this->W = Matrix<double>(this->nhid, this->nvis);
    
    // note: weights are initialized according to the same distribution as in initialize_weights()
    double variation = 4.0*rand_num_uniform_Mersenne_twister(0.0, 1.0)/std::sqrt(std::sqrt(static_cast<double>(nvis*nhid)));
    
    for(int i = 0; i < nhid; ++i)
    {
        for(int j = 0; j < nvis; ++j)
        {
            this->W(i,j) = variation*rand_num_uniform_Mersenne_twister(-0.5, 0.5);
        }
    }
    
    // ... however without data information, it is not as clear how to set the biases
    this->b = Vector<double>(this->nvis, 0.0);
    this->c = Vector<double>(this->nhid, 0.0);
}

inline restricted_Boltzmann_machine::RBM::~RBM() {};